/* Simple JavaScript Inheritance
 * By John Resig http://ejohn.org/
 * MIT Licensed.
 */
// Inspired by base2 and Prototype  灵感来自于base2和Prototype

// 自执行的匿名函数创建一个上下文，避免引入全局变量
(function() {

    // 变量用来标示当前是否处于类的创建阶段
    var initializing = false,

    	// 这里的/xyz/.test(function() {xyz;}) 相当于 /xyz/.test("function() {xyz;}")
    	// 在test()方法中会自动将function(){xyz;} 字符串化 (function(){xyz;}).toString();
    	// 这个fnTest的目的就是为了验证 class method 中是否使用了 "_super()" 调用. 
    	// 这种技术叫做 " function decompilation(函数反编译)" 也叫做 "function serialisation(函数序列化)"， 
    	// Function serialisation 是在一个函数被转换成字符串时发生的. 现在很多浏览器都支持 toString 方法。
    	// /\b_super\b/ 中的 \b 则是限制了开头和结尾，如：_super() 或 _super 是正确的，而 123_super() 或 123_super123 则错误
    	// /.*/ 匹配的是任意字符串
    	// fnTest 被赋值取决于 Function.prototype.toString 是否被实现，
    	// 目前常用的浏览器都已实现了Function.prototype.toString，但是早期的Safari、Mobile Opera、Blackberry Bowser是没有实现的。
        fnTest = /xyz/.test(function() {
            xyz;
        }) ? /\b_super\b/ : /.*/;

    // The base Class implementation (does nothing)
    // 基类，里面什么都不实现，
    // this是window，把Class暴漏给外面
    this.Class = function() {};

    // Create a new Class that inherits from this class
    // 继承的方法定义，继承的主要实现
    Class.extend = function(prop) {

        // this指的是当前调用的对象，
        // 一般是父类调用extend方法，所以这里 _super 保存的是父类的原型对象
        var _super = this.prototype;

        // Instantiate a base class (but only create the instance,
        // don't run the init constructor)
        // 继承了基类（只是继承，没有初始化constructor）

        // 标识已初始化
        initializing = true;
        // prototype（用于新子类的原型） 指向父类构造函数创建的对象
        var prototype = new this();
        // 标识为初始化
        initializing = false;

        // Copy the properties over onto the new prototype
        // 复制所有的子类属性（extend()方法的参数，即子类的扩展定义属性）到用于提供给新子类的原型里
        for (var name in prop) {
            // Check if we're overwriting an existing function
            prototype[name] =
                typeof prop[name] == "function" &&		// 如果该属性是方法
                typeof _super[name] == "function" &&	// 如果该父类有同名属性并且也是方法
                fnTest.test(prop[name]) ?				// 如果子类的该属性方法里写 _super()的方法

                // 则特殊处理覆盖该属性方法
                // 闭包，立即执行了，传入了属性名和属性值（其实是方法名和方法体）
                (function(name, fn) {
                    return function() {
                    	// 用tmp先暂时存储了this._super的引用地址
                        var tmp = this._super;

                        // Add a new ._super() method that is the same method
                        // but on the super-class
                        this._super = _super[name];

                        // The method only need to be bound temporarily, so we
                        // remove it when we're done executing
                        // 把当前的方法执行一下，使用父类的同名方法并传递当前的参数
                        var ret = fn.apply(this, arguments);
                        // 执行完父类的同名方法后，再还原当前自己的this._super引用地址
                        this._super = tmp;

                        // 返回父类同名方法的执行结果
                        return ret;
                    };
                })(name, prop[name]) :
                // 否则直接覆盖
                prop[name];
        }

        // The dummy class constructor
        // 傀儡局部函数 Class，他不是上面说的基类，而是子类，继承了父类之后的产出类
        function Class() {
            // All construction is actually done in the init method
            // 在类的实例化时，调用原型方法init
            if (!initializing && this.init)
                this.init.apply(this, arguments);
        }

        // Populate our constructed prototype object
        // Class（这里的Class是子类）的原型指向父类的原型
        Class.prototype = prototype;

        // Class 原型的构造函数指回本身（修正原型构造函数指向）
        // Enforce the constructor to be what we expect
        Class.prototype.constructor = Class;

        // And make this class extendable
        // 子类自动获取extend方法，arguments.callee指向当前正在执行的函数
        Class.extend = arguments.callee;

        return Class;
    };
})();
